Function.prototype.myCall = function () {
  var object = arguments[0]
  var arr = []
  for (var i = 1; i < arguments.length; i++) {
    arr.push(arguments[i])
  }
  object.__proto__._fn = this
  var result = object._fn(...arr)
  delete object.__proto__._fn
  return result
}

Function.prototype.myCall = function () {
  const obj = arguments[0]
  let args = []
  for (let i = 1; i < arguments.length; i++) {
    args.push(arguments[i])
  }
  object.__proto__._fn = this
  const res = object._fn(...args)
}

Function.prototype.myApply = function (object, arr) {
  object.__proto__._fn = this
  var result = object._fn(...arr)
  delete object.__proto__._fn
  return result
}
// call
var name = '时间跳跃'
var obj = {
  name: '听风是风',
}

function fn(a, b, c) {
  console.log(a + b + c + this.name)
}
//模拟call方法
Function.prototype.call_ = function (obj) {
  //判断是否为null或者undefined,同时考虑传递参数不是对象情况
  // 如果对象不存在就返回window
  obj = obj ? Object(obj) : window
  var args = []
  // 注意i从1开始
  for (var i = 1, len = arguments.length; i < len; i++) {
    // 因为eval的时候会不带引号，所以要用arguments过渡一下
    args.push('arguments[' + i + ']')
  }
  obj.fn = this // 此时this就是函数fn
  eval('obj.fn(' + args + ')') // 执行fn
  // 执行obj.fn，因为隐式绑定的问题，fn内部的this指向obj
  delete obj.fn //删除fn
}
fn.call_(obj, '我的', '名字', '是') // 我的名字是听风是风
fn.call_(null, '我的', '名字', '是') // 我的名字是时间跳跃
fn.call_(undefined, '我的', '名字', '是') // 我的名字是时间跳跃

// ES6
// ES6 call
Function.prototype.call_ = function (obj) {
  // 这里obj只接受了第一个参数，剩余的参数用剩余参数取接受
  obj = obj ? Object(obj) : window
  // obj.fn继承了原来fn的this
  obj.fn = this
  // 利用拓展运算符直接将arguments转为数组
  let args = [...arguments].slice(1)
  // 执行一下fn
  let result = obj.fn(...args)

  delete obj.fn
  return result
}

Function.prototype.call_ = function (obj) {
  // 考虑参数不是对象，以及参数是null或者undefined的情况
  obj = obj ? Object(obj) : window
  obj.fn = this
  let args = [...arguments].slice(1)
  let res = obj.fn(args)
  // 用完记得删除
  delete obj.fn
  return res
}
// ES6 apply
Function.prototype.apply_ = function (obj, arr) {
  obj = obj ? Object(obj) : window
  obj.fn = this
  let result
  // 避免参数为空 args is not iterable
  if (!arr) {
    result = obj.fn()
  } else {
    result = obj.fn(...arr)
  }
  delete obj.fn
  return result
}

Function.prototype.apply_ = function (obj, arr) {
  obj = obj ? Object(obj) : window
  obj.fn = this
  let res
  if (!arr) {
    obj.fn()
  } else {
    obj.fn(...arr)
  }
  delete obj.fn
  return res
}
